import java.io._
import java.time.LocalDate
import scala.collection.mutable
import scala.io.StdIn.readLine

// 会员类
case class Member(
                   cardNumber: String,
                   name: String,
                   password: String,
                   var points: Int,
                   registerTime: LocalDate
                 ) extends java.io.Serializable

// 超市类
case class Supermarket(
                        name: String,
                        address: String,
                        phone: String,
                        members: mutable.Map[String, Member],
                        gifts: List[(Int, String)]  // 礼品列表
                      ) extends java.io.Serializable

// 数据持久化工具
object DataPersistence {
  val FILENAME = "supermarket.dat"

  // 保存超市数据到文件
  def saveSupermarket(supermarket: Supermarket): Unit = {
    val fileOut = new FileOutputStream(FILENAME)
    val objectOut = new ObjectOutputStream(fileOut)
    objectOut.writeObject(supermarket)
    objectOut.close()
    fileOut.close()
  }

  // 从文件加载超市数据
  def loadSupermarket(): Option[Supermarket] = {
    if (new File(FILENAME).exists()) {
      val objectIn = new ObjectInputStream(new FileInputStream(FILENAME))
      val supermarket = objectIn.readObject().asInstanceOf[Supermarket]
      objectIn.close()
      Some(supermarket)
    } else {
      None
    }
  }
}

// 超市会员管理系统
object SupermarketSystem {
  def main(args: Array[String]): Unit = {
    var supermarket = DataPersistence.loadSupermarket().getOrElse(
      Supermarket("My Supermarket", "123 Main St", "1234567890", mutable.Map(), List(
        (1000, "一个炒锅"),
        (800, "一瓶洗手液"),
        (400, "一包餐巾纸")
      ))
    )

    def registerMember(): Unit = {
      print("请输入注册姓名：")
      val name = readLine()

      print("请输入注册密码：")
      var password = readLine()

      // 确保密码长度至少为6位
      while (password.length < 6) {
        println("会员密码不能小于6位，请重新输入注册密码：")
        password = readLine()
      }

      // 生成会员卡号（示例：随机生成）
      val cardNumber = (100000 + scala.util.Random.nextInt(900000)).toString()

      // 创建新会员
      val member = Member(
        cardNumber,
        name,
        password,
        points = 100, // 系统赠送100积分
        registerTime = LocalDate.now()
      )

      // 将新会员添加到超市的会员列表中
      if (supermarket.members.contains(cardNumber)) {
        println("生成的会员卡号已存在，请重新开卡！")
        registerMember() // 递归调用，重新开卡
      } else {
        supermarket.members.put(cardNumber, member)
        println(s"恭喜，开通会员卡成功，系统赠送您100积分！您的会员卡号为：$cardNumber")
        DataPersistence.saveSupermarket(supermarket) // 保存超市数据
      }
    }

    def accumulatePoints(): Unit = {
      print("请输入您的会员卡号：")
      val cardNumber = readLine()
      print("请输入您的会员卡密码：")
      val password = readLine()
      print("请输入消费金额（消费1元累计1积分）：")
      val amount = readLine.toInt

      val member = supermarket.members.get(cardNumber)
      if (member.isEmpty || member.get.password != password) {
        println("卡号或密码错误！")
        return
      }

      if (amount <= 0) {
        println("消费金额必须大于0！")
        return
      }

      member.get.points += amount
      println("积分累计成功")
      DataPersistence.saveSupermarket(supermarket) // 保存超市数据
    }

    def queryPoints(): Unit = {
      print("请输入卡号：")
      val cardNumber = readLine()
      print("请输入密码：")
      val password = readLine()

      val memberOpt = supermarket.members.get(cardNumber)
      if (memberOpt.isEmpty || memberOpt.get.password != password) {
        println("卡号或密码错误！")
        return
      }

      val member = memberOpt.get
      println(s"姓名 会员卡号 剩余积分 开卡日期")
      println(s"${member.name} ${member.cardNumber} ${member.points} ${member.registerTime}")
    }

    def changePassword(): Unit = {
      print("请输入您的会员卡号：")
      val cardNumber = readLine()
      print("请输入您的会员卡密码：")
      val password = readLine()

      val memberOpt = supermarket.members.get(cardNumber)
      if (memberOpt.isEmpty || memberOpt.get.password != password) {
        println("卡号或密码错误！")
        return
      }

      var newPassword = ""
      while (newPassword.length < 6) {
        print("请输入新的会员密码：")
        newPassword = readLine()
        if (newPassword.length < 6) {
          println("密码必须至少6位，请重新输入！")
        }
      }

      // 使用 copy 方法创建新的 Member 实例
      val updatedMember = memberOpt.get.copy(password = newPassword)

      // 更新成员信息
      supermarket.members.put(cardNumber, updatedMember)
      println("密码修改成功！")
      DataPersistence.saveSupermarket(supermarket) // 保存超市数据
    }

    def redeemGift(): Unit = {
      print("请输入卡号：")
      val cardNumber = readLine()
      print("请输入密码：")
      val password = readLine()

      val member = supermarket.members.get(cardNumber)
      if (member.isEmpty || member.get.password != password) {
        println("卡号或密码错误！")
        return
      }

      println("1:1000积分 兑换一个炒锅")
      println("2:800积分 兑换一瓶洗手液")
      println("3:400积分 兑换一包餐巾纸")

      print("请选择：")
      val choice = readLine.toInt - 1

      val pointsNeeded = if (choice >= 0 && choice < supermarket.gifts.size) {
        supermarket.gifts(choice)._1
      } else {
        println("无效选择，请重新输入！")
        return
      }

      if (member.get.points < pointsNeeded) {
        println("积分不足，兑换失败！")
        return
      }

      member.get.points -= pointsNeeded
      println(s"兑换${supermarket.gifts(choice)._2}成功")
      DataPersistence.saveSupermarket(supermarket)
    }

    def exitSystem(): Unit = {
      println("退出系统，再见！")
      DataPersistence.saveSupermarket(supermarket)
      System.exit(0)
    }

    while (true) {
      println("**************************** 欢迎进入超市会员管理系统 *****************************")
      println("1. 积分累计")
      println("2. 积分兑换")
      println("3. 查询剩余积分")
      println("4. 修改密码")
      println("5. 开卡")
      println("6. 退出")
      println("****************************************************************************************************")
      print("请选择：")

      val choice = readLine.toInt

      choice match {
        case 1 => accumulatePoints()
        case 2 => redeemGift()
        case 3 => queryPoints()
        case 4 => changePassword()
        case 5 => registerMember()
        case 6 => exitSystem()
        case _ => println("无效选择，请重新输入！")
      }
    }
  }
}